package org.example;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.*;
import org.junit.jupiter.api.Assertions;

import java.util.*;
import java.util.function.Function;

import static cn.hutool.core.lang.Console.*;

/**
 * 南方1 北方2 分不清3
 * @author dcm
 */
public class Magic {
    public static void main(String[] args) {
        Set<String> cards = Sets.newHashSet("A", "2", "3", "4",
                "5", "6", "7", "8", "9", "10", "J", "Q", "K");
        Set<String> yourCards = Sets.newHashSet();
        log("请从中选择四张你喜欢的卡牌，逗号分隔 {}：",cards);
        Scanner scanner = scanner();
        yourCards = scannerWhile(yourCards,o -> {
            String cardsStr = scanner.nextLine();
            o = Sets.newHashSet(StrUtil.split(cardsStr, ",", true,true));
            log("选择的卡牌：{}，卡牌数：{}",o,o.size());
            Assertions.assertEquals(4, o.size(),"卡牌数错误，请从新选择不同的四张牌：");
            Assertions.assertTrue(cards.containsAll(o),"卡牌错误，请从新选择不同的四张牌：");
            return o;
        });
        List<String> selectCards = Lists.newArrayList(Iterables.concat(yourCards, yourCards));
        log("对折后的卡牌：{}",selectCards);
        log("请输入姓名，用于将前面的卡牌插入队尾：");
        Integer nameCount = 0;
        nameCount = scannerWhile(nameCount,o -> {
            o = scanner.nextLine().length();
            Assertions.assertTrue(Range.closed(2,7).contains(o),
                    "姓名长度为："+o+"，你的名字比尼格买提还奇怪");
            return o;
        });
        Collections.rotate(selectCards, -nameCount);
        log("将前面{}张卡牌插入队尾，插入后的卡牌为：{}：",nameCount,selectCards);
        selectCards.addAll(RandomUtil.randomInt(4, 7), selectCards.subList(0, 3));
        selectCards.subList(0, 3).clear();
        log("将队头的三张卡牌插入中间，插入后的卡牌为：{}：",selectCards);
        String butt = selectCards.remove(0);
        log("将第一张牌放入屁股下，屁股下的牌为：({}),剩余的牌为：{}",butt,selectCards);
        log("请输入性别男扔一张牌 女扔两张牌：");
        BiMap<String,Integer> genderBiMap = HashBiMap.create(Map.of("男", 1, "女", 2));
        Integer gender = null;
        gender = scannerWhile(gender,o -> {
            String genderScan = scanner.nextLine();
            o = genderBiMap.get(genderScan);
            Assertions.assertNotNull(o,"性别错误");
            return o;
        });
        selectCards.subList(0, gender).clear();
        log("您的性别是：{},去除{}张牌后，剩余的牌为：{}",genderBiMap.inverse().get(gender),gender,selectCards);
        Collections.rotate(selectCards, -7);
        log("《见证奇迹的时刻》，卡牌循环七次后：{}",selectCards);
        scannerWhile(selectCards,coll -> {
            coll.add(coll.remove(0));
            log("好运留下来",coll);
            coll.remove(0);
            log("烦恼丢出去",coll);
            if (coll.size() <= 1) {
                log("此时，您的卡牌剩余{}张，剩余的牌是{}，屁股下的牌是：{}",coll.size(),coll,butt);
                Assertions.assertEquals(butt,coll.get(0),"您也是全国唯一一个没对上的！");
                return true;
            }
            return null;
        });
        scanner.close();
    }
    public static <T,R> R scannerWhile(T object, Function<T, R> func) {
        R r;
        while (true) {
            try {
                r = func.apply(object);
                if (r != null) break;
            } catch (Throwable e){
                log(StrUtil.subBefore(e.getMessage(), "==>", false));
            }
        }
        return r;
    }

}
